/**
 * @file applicationLib.c
 * @brief Sorgente contenente le funzioni dell'entità Receiver seguendo il pattern Facade.
 *
 * Con queste funzioni è possibile utilizzare le sottoclassi in maniera semplificata.
 * I dati da utilizzare sono instanziati nella corrispettiva struttura dati all'interno del
 * header file che definisce il pattern command e le sue relazioni con l'invoker (invoker.h).
 *
 * @see invoker.h file dove viene definita la struttura del receiver e del command.
 *
 * @date Mar 1, 2012
 * @author Francesco Corvino
 */
#include <pthread.h>

#include "applicationLib.h"
#include "../logproxy/logproxy.h"

////////////////////////////////////////////////////////////////////////////////////////
////// Funzioni per gestire le risorse di memoria //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////

/**
 * @brief Restituisce un attributo dell'applicazione
 *
 * L'attributo restituito, essendo l'ambiente concorrenziale, rappresenta un duplicato.
 *
 * @param key intero che indica l'attributo da ricavare
 * @return l'attributo richiesto e NULL se l'attributo non esiste.
 */
void * AppLib_getAttribute(const int key){
	return RscApp_getAttribute(key);
}

/**
 * @brief Aggiunge o modifica gli attributi in memoria.
 *
 * @param key chiave rappresentante l'attributo.
 * @param value valore da attribuire all'attributo.
 * @param dim dimensione dell'attributo.
 *
 */
void AppLib_setAttribute(const int key, void * value, size_t dim) {
	RscApp_setAttribute(value,key,dim);
}

/**
 * @brief permette di effettuare operazioni atomiche su specifici attributi.
 *
 * Se l'attributo non esiste, l'operazione non viene eseguita. La chiamata
 * assicura che le risorse non vengano cambiate durante il periodo di esecuzione
 * dell'operazione.
 *
 * @param key chiave dell'attributo su cui effettuare l'operazione.
 * @param oper operazione da eseguire.
 *
 * @return -1 se l'operazione non è stata eseguita, altrimenti restituisce il valore dell'operazione.
 */
int AppLib_atomicOperOnAttr(const int key,int (*oper)(void*)) {
	//TODOH funzione non implementata
	return -1;
}

////////////////////////////////////////////////////////////////////////////////////////
//////  Funzioni per la gestione delle risorse dell'Host   /////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////

/**
 * @brief Restituisce la sessione relativa al thread.
 */
HostSession* AppLib_getMySession(){
	return FactComm_getSessionFor(pthread_self());
}

/**
 * @brief Cancella la sessione relativa alla thread chiamante.
 *
 * Non tutte le sessioni possono essere cancellate, dipende dal tipo di sessione
 * avviata.
 */
void AppLib_closeMySession(){
	HostSession* session = FactComm_getSessionFor(pthread_self());
	FactComm_deleteSession(session);
}

/**
 * @brief Effettua la scrittura della stringa passata sul rispettivo output con cui la thread sta comunicando.
 *
 * La funzione ricava la sessione dal tid della thread che invoca la stessa funzione.
 * Viene poi invocata la funzione @see Session_Write che si occupa di scrivere un determinato messaggio
 * sulla sessione ricavata.
 *
 * @param msg stringa da inviare.
 */
void AppLib_writeToHost(char * msg){
	// ricava l'entità con cui sta comunicando la thread
	pthread_t tid = pthread_self();
	HostSession* session = FactComm_getSessionFor(tid);
	Session_Write(session,msg, strlen(msg));
}

/**
 * @brief Funzione che permette la scrittura sull'host della rispettiva sessione passando degli
 * argomenti e la corrispettiva formattazione.
 *
 * La funzione fa utilizzo di <code>vsprintf</code> per ottenere una stringa formattata secondo
 * gli argomenti passati utilizzando <code>va_list</code>. In seguito viene richiamata la stessa
 * funzione @see AppLib_writeToHost per stampare la stringa formattata ottenuta.
 */
void AppLib_writeToHostF(char *fmt,...){
	  va_list args;	char msgToWrite[255];
	  va_start( args, fmt );
	  vsprintf( msgToWrite, fmt, args );
	  va_end( args );
	  AppLib_writeToHost(msgToWrite);
}

/**
 * @brief Restituisce l'input dell'utente.
 */
int AppLib_readFromHost(char *buf, int maxsize){
	pthread_t tid = pthread_self();
	HostSession* session = FactComm_getSessionFor(tid);
	int byte = Session_Read(session,buf, maxsize);
	return byte;
}

/**
 * @brief Restituisce un parametro fornito dall'utente.
 *
 * Il parametro deve essere impostato tramite la stessa request, la funzione
 * controlla che il parametro sia nella request, se presente lo restituisce altrimenti
 * restituisce 0.
 *
 * @param param nome del parametro da ricercare.
 * @param value puntatore al buffer dove inserire il valore del parametro letto.
 * @param maxsize dimensione massima disponibile per la scrittura in value.
 * @return numero di byte inseriti.
 */
int AppLib_getParam(char* param, char* value, int maxsize){
	log_namedlevel(NAMELOG_APPLICATION_LIB, LOG_INFO_LEVEL,
			"Cerco il parametro %s ",param);
	int byte = 0;
	HostSession* session = FactComm_getSessionFor(pthread_self());
	// individua tramite la chiave di sessione la richiesta corrente
	UserRequest* req = RscApp_getRequest(session->keySession);
	if(req!=NULL) { // se si ha una richiesta per la sessione corrente
		//controlla i parametri impostati alla request
		UserParam* p = UserParam_getFromDynArray(&(req->params),param);
		if(p!=NULL) {
			byte= NUMERICMIN(maxsize,(strlen(p->value)+1));
			memcpy(value,p->value,byte);
		}
	}
	return byte;
}

/**
 * @brief avvia le operazione di terminazione liberando le risorse occupate.
 */
void AppLib_terminate() {
	//TODO gestire le risorse?
	exit(0);
}
